﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using HandyControl.Controls;
using HandyControl.Data;
using Koala.Pro.Common;
using Koala.Pro.Core;
using Koala.Pro.Core.Dto;
using Koala.Pro.Helpers;
using Koala.Pro.Models;
using Koala.Pro.Services;
using System.Data;
using System.Diagnostics;
using System.Windows;

namespace Koala.Pro.ViewModels
{
    public abstract partial class BaseListViewModel<TEntity, TKey, TGetListInput> : BaseViewModel where TEntity : class, IEntity<TKey>, new() where TGetListInput : IPagedAndSortedResultRequest, new()
    {
        [ObservableProperty]
        private List<TEntity>? items;

        [ObservableProperty]
        private List<TEntity>? selectedItems;

        [ObservableProperty]
        private PagingData pagerInfo = new PagingData();

        [ObservableProperty]
        private TGetListInput pageDto = new TGetListInput();

        protected string ExportFields = "";

        protected IMyCrudService<TEntity, TKey, TGetListInput> service { get; set; }

        public BaseListViewModel(IMyCrudService<TEntity, TKey, TGetListInput> service)
        {
            this.service = service;
        }

        public override async void OnNavigatedTo()
        {
            base.OnNavigatedTo();
            await GetData();
        }

        [RelayCommand]
        private async Task PageUpdated(FunctionEventArgs<int> info)
        {
            PagerInfo.CurrentPageIndex = info.Info;
            await GetData();
        }

        [RelayCommand]
        public virtual async Task Search()
        {
            PagerInfo.CurrentPageIndex = 1;
            await GetData();
        }

        [RelayCommand]
        public async Task Delete(TEntity info)
        {
            if (info != null && MessageDxUtil.ShowYesNoAndWarning("您确认删除该记录？") == MessageBoxResult.Yes)
            {
                bool success = await DeleteData(info);
                if (success)
                {
                    await GetData();
                }
                string text = (success ? "删除操作成功" : "删除操作失败");
                base.Result = new CommonResult(success, text);
                if (success)
                {
                    Growl.SuccessGlobal(text);
                }
                else
                {
                    Growl.ErrorGlobal(text);
                }
            }
        }

        [RelayCommand]
        public async Task BatchDelete()
        {
            if (SelectedItems != null && MessageDxUtil.ShowYesNoAndWarning("您确认批量删除选定的记录？") == MessageBoxResult.Yes)
            {
                IEnumerable<TKey> idList = SelectedItems.Select((TEntity s) => s.Id);
                bool success = await service.DeleteAsync((TEntity s) => idList.Contains(s.Id));
                if (success)
                {
                    await GetData();
                }
                string text = (success ? "批量删除操作成功" : "批量删除操作失败");
                base.Result = new CommonResult(success, text);
                if (success)
                {
                    Growl.SuccessGlobal(text);
                }
                else
                {
                    Growl.ErrorGlobal(text);
                }
            }
        }

        protected virtual void ConvertPagingInfo()
        {
            TGetListInput val = PageDto;
            val.SkipCount = (PagerInfo.CurrentPageIndex - 1) * PagerInfo.PageSize;
            val = PageDto;
            val.MaxResultCount = PagerInfo.PageSize;
        }

        public virtual async Task GetData()
        {
            ConvertPagingInfo();
            PagedResultDto<TEntity> pagedResultDto = await service.GetListAsync(PageDto);
            if (pagedResultDto != null)
            {
                Items = pagedResultDto.Items?.ToList();
                PagerInfo.RecordCount = pagedResultDto.TotalCount;
            }
            NotifyChanged();
        }

        protected virtual async Task<bool> DeleteData(TEntity info)
        {
            return await service.DeleteAsync(info.Id);
        }

        public new void NotifyChanged(string propertyName = "Items")
        {
            OnPropertyChanged(propertyName);
        }

        [RelayCommand]
        protected virtual async Task ExportPdf(string title = "列表数据")
        {
            BaseExportPdf(await ConvertItems(Items), title);
        }

        [RelayCommand]
        protected virtual async Task ExportExcel(string title = "列表数据")
        {
            BaseExportExcel(await ConvertItems(Items), title);
        }

        public async Task<DataTable> ConvertItems(List<TEntity>? items)
        {
            DataTable table = items.ToDataTable();
            if (!ExportFields.IsNullOrEmpty())
            {
                List<string> source = ExportFields.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList();
                List<string> list = new List<string>();
                foreach (DataColumn column in table.Columns)
                {
                    if (!source.Contains<string>(column.ColumnName, StringComparer.CurrentCultureIgnoreCase))
                    {
                        list.Add(column.ColumnName);
                    }
                }
                foreach (string item in list)
                {
                    table.Columns.Remove(item);
                }
            }
            Dictionary<string, string> dictionary = await service.GetColumnNameAlias();
            if (dictionary != null && dictionary.Count > 0)
            {
                foreach (DataColumn column2 in table.Columns)
                {
                    if (dictionary.ContainsKey(column2.ColumnName))
                    {
                        column2.Caption = dictionary[column2.ColumnName];
                    }
                }
            }
            return table;
        }

        public virtual async void BaseExportExcel(DataTable table, string title = "列表数据")
        {
            string text = FileDialogHelper.SaveExcel($"{title}.xls");
            if (string.IsNullOrEmpty(text))
            {
                return;
            }
            try
            {
                string error = "";

                await Task.Run(() => { AsposeExcelTools.DataTableToExcel2(table, text, out error); });

                if (!string.IsNullOrEmpty(error))
                {
                    MessageDxUtil.ShowError($"导出Excel出现错误：{error}");
                }
                else if (MessageDxUtil.ShowYesNoAndTips("导出成功，是否打开文件？") == MessageBoxResult.Yes)
                {
                    Process.Start("explorer.exe", text);
                }
            }
            catch (Exception ex)
            {
                LogTextHelper.Error(ex);
                MessageDxUtil.ShowError(ex.Message);
            }
        }

        public virtual async void BaseExportPdf(DataTable table, string title = "列表数据")
        {
            string text = FileDialogHelper.SavePdf(title);
            if (!text.IsNullOrEmpty())
            {
                bool isLandscape = true;
                bool includeHeader = true;
                iText.Layout.Properties.HorizontalAlignment headerAlignment = iText.Layout.Properties.HorizontalAlignment.CENTER;
                float headerFontSize = 9f;
                float rowFontSize = 9f;

                bool num = await Task.Run(() =>
                {
                    return TextSharpHelper.ExportTableToPdf(title,
                    table,
                    text,
                    isLandscape,
                    includeHeader,
                    headerAlignment,
                    headerFontSize,
                    rowFontSize);
                });

                string message = (num ? "导出操作成功" : "导出操作失败");
                if (num)
                {
                    Growl.SuccessGlobal(message);
                    Process.Start("explorer.exe", text);
                }
                else
                {
                    Growl.ErrorGlobal(message);
                }
            }
        }
    }
}
